#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/sem.h>

#include "semmun.h"

static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);

static int sem_id;

int main(int argc,char * argv[])
{
	int i;
	int pause_time;
	char op_char = 'O';

	srand((unsigned int)getpid());//为rand提供种子数值？？

	sem_id = semget((key_t) 1234,1,0666| IPC_CREAT);//创建一个新的信号量。或者获取一个已有信号量的值

	if (argc > 1) {
		if (!set_semvalue()) {
			fprintf (stderr,"Failed to initialize semaphore");
			exit(EXIT_FAILURE);
		}
		op_char = 'X';
		sleep(2);
	}

	printf ("Prepare semaphore....\n");
	for(i = 0;i < 10;i++) {
		if (!semaphore_p()) exit (EXIT_FAILURE);//先操作信号量，堵塞其它进程来访问它。
		printf("%c",op_char);fflush(stdout);
		pause_time = rand() % 3;
		//printf("pause_time value is [%d]\n",pause_time);
		sleep(pause_time);
		printf("%c",op_char);fflush(stdout);
		if (!semaphore_v()) exit(EXIT_FAILURE);

		pause_time = rand() % 2;
		sleep (pause_time);
	}
	
	printf("\n%d - finished\n",getpid());

	if (argc > 1) {
		sleep(10);
		del_semvalue();
	}

	exit (EXIT_SUCCESS);
}

static int set_semvalue(void) 
{
	union semun sem_union;

	sem_union.val = 1;//不知道为什么是1，注释后会怎么样？？

	if (semctl(sem_id,0,SETVAL,sem_union) == -1) return 0;
	return(1);

}


static void del_semvalue (void) 
{
	union semun sem_union;

	if (semctl (sem_id, 0, IPC_RMID,sem_union) == -1 )
		fprintf (stderr, "Failed to delete semaphore\n");
	else
		printf ("semaphore is deleted\n");
}

static int semaphore_p (void )
{
	struct sembuf sem_b;

	sem_b.sem_num = 0;
	sem_b.sem_op  = -1;//P ()
	sem_b.sem_flg = SEM_UNDO;
	if (semop (sem_id, &sem_b, 1) == -1 ) {
		fprintf (stderr,"semaphore_p Failed\n");
		return 0;

	}
	return 1;

}



static int semaphore_v (void )
{
	struct sembuf sem_b;

	sem_b.sem_num = 0;
	sem_b.sem_op  = 1;//V ()
	sem_b.sem_flg = SEM_UNDO;
	if (semop (sem_id, &sem_b, 1) == -1 ) {
		fprintf (stderr,"semaphore_v Failed\n");
		return 0;

	}
	return 1;
}











